package com.miyake.dsp.osa.method;

import java.util.ArrayList;
import java.util.List;

import com.miyake.dsp.common.CommonTool;
import com.miyake.dsp.common.UnitConverter;
import com.miyake.dsp.osa.AnalysisProperty;
import com.miyake.dsp.osa.lab.Fitting2;

public class IEC implements NFCalc {
	private double ase;
	private double gain;

	private List<double[]> traces = new ArrayList<double[]>();
	private double[] subX;
	private double fittingStart;
	private double fittingEnd;
	private double maskedStart;
	private double maskedEnd;

	@Override
	public void setData(double[] x, double[] in, double[] out,
			AnalysisProperty setting, boolean fitInLog,
			int peakIndex, int outPeakIndex, int peakCenterIndex, double center) {
		traces.clear();

		this.fittingStart = setting.getFittingStart();
		this.fittingEnd = setting.getFittingEnd();
		this.maskedStart = center - setting.getMaskedSpan()/2.0;
		this.maskedEnd = center + setting.getMaskedSpan()/2.0;

		Extractor extractor = new Extractor(x);
		extractor.addData(in, "Pin");
		extractor.addData(out, "Pout");

		if (setting.isPoint()) {
			extractor.setPoint(setting.getFittingStart(), setting.getFittingEnd());
		}
		else {
			extractor.setArea(setting.getFittingStart(), setting.getFittingEnd(), this.maskedStart, this.maskedEnd);
		}
		subX = extractor.getBaseToBeFilled();
		double[] originalX = extractor.getFittingDataX();
		double[] originalIn = extractor.getFittingData("Pin");
		double[] originalOut = extractor.getFittingData("Pout");

//		int peakIndexIn2 = peakIndex - extractor.getiStart();
		int peakIndexIn2 = peakCenterIndex - extractor.getiStart();
		int peakIndexOut2 = outPeakIndex - extractor.getiStart();
//		peakIndexOut2 = peakIndexIn2;

		Fitting2 fitting = new Fitting2(setting.getFormula());

		NormalizeX nx = new NormalizeX(originalX, subX);

		// OUT波形フィッティング
		if (fitInLog) {
			fitting.setOriginalData(nx.getNomalizedOriginal(), UnitConverter.todBm(originalOut));
		}
		else {
			fitting.setOriginalData(nx.getNomalizedOriginal(), originalOut);
		}

		double[] outfit = fitting.getInterpolated(nx.getNomalizedInterpolate());
		if (fitInLog) {
			outfit = UnitConverter.toW(outfit);
		}

		// Nout算出（仮ASE）
		double outValue = outfit[peakIndexIn2]; // In基準

		traces.add(outfit);

		// Pin波形フィッティング
		if (fitInLog) {
			fitting.setOriginalData(nx.getNomalizedOriginal(), UnitConverter.todBm(originalIn));
		}
		else {
			fitting.setOriginalData(nx.getNomalizedOriginal(), originalIn);
		}

		double[] infit = fitting.getInterpolated(nx.getNomalizedInterpolate());
		if (fitInLog) {
			infit = UnitConverter.toW(infit);
		}
		double inValue = infit[peakIndexIn2];//fitting.getAt(center);

		traces.add(infit);

		// 横河の仮ゲイン
		gain = (out[outPeakIndex] - outfit[peakIndexIn2]) / in[peakIndex]; // IN基準

		ase = outValue - inValue * gain;
	}

	@Override
	public double getAse() {
		return ase;
	}

	@Override
	public double getGain() {
		return gain;
	}

	@Override
	public List<double[]> getTraces() {
		return traces;
	}

	@Override
	public double[] getSubX() {
		return this.subX;
	}

	@Override
	public Double getFittingStart() {
		return this.fittingStart;
	}

	@Override
	public Double getFittingEnd() {
		return this.fittingEnd;
	}

	@Override
	public Double getMaskedStart() {
		return this.maskedStart;
	}

	@Override
	public Double getMaskedEnd() {
		return this.maskedEnd;
	}

}
